﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Threading;
using Core.Class;
using Core.Class.Synchronize;
using Core.ViewModel;
using Database.POCO;
using GalaSoft.MvvmLight.Ioc;
using Helpers.Mef;
using Interfaces;
using Interfaces.Contracts;
using Navegar;

namespace Core.Views
{
    /// <summary>
    /// Logique d'interaction pour SpashScreen.xaml
    /// </summary>
    public partial class SplashScreen : Window
    {

        #region properties

        public IServiceDatabase DatabaseService
        {
            get { return SimpleIoc.Default.GetInstance<IServiceDatabase>(); }
        }

        public IServiceLocalize LocalizedService
        {
            get { return SimpleIoc.Default.GetInstance<IServiceLocalize>(); }
        }

        [ImportMany(typeof (IRights))]
        public IEnumerable<Lazy<IRights>> RightsModule { get; set; }

        [ImportMany(typeof (IParameters))]
        public IEnumerable<Lazy<IParameters>> ParametersModule { get; set; }

        #endregion

        /// <summary>
        /// 
        /// </summary>
        public SplashScreen()
        {
            InitializeComponent();
            CompositionInitializer.AddPartAndComposeContainer(this);
            this.Loaded += SplashLoaded;
        }

        #region private

        private void SplashLoaded(object sender, RoutedEventArgs e)
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback(state => LoadApplication()), null);
        }

        private void LoadApplication()
        {
            LoadApp();

            //Lancement de la fenêtre principale de l'application
            this.Dispatcher.BeginInvoke(DispatcherPriority.Send, new DispatcherOperationCallback(delegate(Object state)
            {
                this.Hide();

                //Enregistrement du MainVieWModel
                SimpleIoc.Default.GetInstance<INavigation>().GenerateMainViewModelInstance<MainViewModel>();

                //Chargement de la fenêtre principale
                var window = new MainWindow();
                window.Show();
                this.Close();
                return null;
            }), null);
        }

        /// <summary>
        /// Permet de charger les composantes de l'application
        /// </summary>
        private async void LoadApp()
        {
            bool loadRights = false;
            bool loadLabels = false;
            bool loadParameters = false;
#if DEBUG
            loadRights = true;
            loadLabels = true;
            loadParameters = true;
#else
            //En mode release on regarde si les tables sont vides avant de lancer le chargement des données
            loadRights = !DatabaseService.Service.GetAll<SysDroits>().ToList().Any();
            loadLabels = !DatabaseService.Service.GetAll<SysLabels>().ToList().Any();
            loadParameters = !DatabaseService.Service.GetAll<SysParametres>().ToList().Any();
#endif

            //1. D'abord le chargement des labels car les droits et les paramétres utilisent ce service
            if (loadLabels)
            {
                Application.Current.Dispatcher.Invoke((Action) (() =>
                {
                    MessagesTextBlock.Text = "Préparation de l'interface...";
                }));
                LocalizedService.InitialLocalizedValues();
            }

            //2. On charge en mémoire les labels pour l'interface
            LocalizedService.LoadLocalizedValues();

            //3.Gestion des droits
            if (loadRights)
            {
                Application.Current.Dispatcher.Invoke((Action) (() =>
                {
                    MessagesTextBlock.Text = "Préparation des droits...";
                }));
                LoadRightsModules();
            }

            //3. Gestion des parametres
            if (loadParameters)
            {
                Application.Current.Dispatcher.Invoke((Action) (() =>
                {
                    MessagesTextBlock.Text = "Préparation des paramètres...";
                }));
                LoadParametersModules();
            }

            //4. Si l'on peut on synchronise les données
            if (CurrentParametersInRunning.IsNetworkAvailable)
            {
                Application.Current.Dispatcher.Invoke((Action) (() =>
                {
                    MessagesTextBlock.Text = "Préparation de la synchronisation...";
                }));
                await Synchronisation.Synchronize();
            }
        }

        /// <summary>
        /// Permet de généner les droits pour les modules
        /// </summary>
        private void LoadParametersModules()
        {
            if (ParametersModule != null && ParametersModule.Any())
            {
                foreach (var mod in ParametersModule)
                {
                    mod.Value.Initialized();
                    var parameters = mod.Value.GetParameters();
                    if (parameters != null && parameters.Any())
                    {
                        foreach (var parameter in mod.Value.GetParameters())
                        {
                            if (!DatabaseService.Service.Where<SysParametres>(d => d.Module == parameter.Module && d.Index == parameter.Index).Any())
                            {
                                DatabaseService.Service.Save<SysParametres>(parameter);
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Permet de généner les droits pour les modules
        /// </summary>
        private void LoadRightsModules()
        {
            if (RightsModule != null && RightsModule.Any())
            {
                foreach (var mod in RightsModule)
                {
                    mod.Value.Initialized();
                    var rights = mod.Value.GetRights();
                    if (rights != null && rights.Any())
                    {
                        foreach (var right in mod.Value.GetRights())
                        {
                            if (!DatabaseService.Service.Where<SysDroits>(d => d.IdentifiantDroit == right.IdentifiantDroit).Any())
                            {
                                DatabaseService.Service.Save<SysDroits>(right);
                            }
                        }
                    }
                }
            }
        }

        #endregion
    }
}
